/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.kurvykurvy.page;

import com.kurvykurvy.image.LoadedImage;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.Vector;

/**
 *
 * @author HY
 */
public class ImageFrameImpl
    implements ImageFrame
{
    protected Point location = new Point( 0, 0 );

    private ImageFrameTemplate template;
    private LoadedImage loadedImage;

    Vector<AffineTransform> transformationList;

    BufferedImage bufferedImage;

    public ImageFrameImpl( ImageFrameTemplate template, LoadedImage img )
    {
        this.template = template;
        this.loadedImage = img;
    }

    public ImageFrameImpl( ImageFrameTemplate template, BufferedImage img )
    {
        this.template = template;
        this.loadedImage = new LoadedImage( img );
    }

    public ImageFrameTemplate getTemplate()
    {
        return template;
    }

    /**
     * @param template the template to set
     */
    public void setTemplate( ImageFrameTemplate template )
    {
        this.template = template;
    }

    public AffineTransform generateTransform()
    {
        AffineTransform result = new AffineTransform();
        System.out.println( "Generating transform:" );
        System.out.println( "\t Start Scale X : " + result.getScaleX() );
        System.out.println( "\t Start Scale Y : " + result.getScaleY() );
        if( this.transformationList != null )
        {
            AffineTransform transformation = null;
            for( Iterator<AffineTransform> it = this.transformationList.iterator(); it.hasNext(); )
            {
                transformation = it.next();
                result.concatenate( transformation );
            }
        }
        return result;
    }

    public void generateBufferedImage()
    {
        AffineTransform transform = generateTransform();
        System.out.println( "Generate Buffered Image Scale X : " + transform.getScaleX() );
        System.out.println( "Generate Buffered Image Scale Y : " + transform.getScaleY() );
        Dimension resultSize = new Dimension( (int) ( this.loadedImage.getSize().getWidth() * transform.getScaleX() ), (int) ( this.loadedImage.getSize().getHeight() * transform.getScaleY() ) );
        if( resultSize.width <= 0 || resultSize.height <= 0 )
        {
            resultSize = getSize();
        }
        System.out.println( "Scaled Image size : " + resultSize.width + ", " + resultSize.height );

        BufferedImage image = new BufferedImage( resultSize.width, resultSize.height, BufferedImage.TYPE_INT_ARGB );

        Graphics2D g2 = image.createGraphics();
        if( this.loadedImage != null && this.loadedImage.getSourceImage() != null )
        {
            g2.drawImage( this.loadedImage.getSourceImage().getScaledInstance( resultSize.width, resultSize.height, Image.SCALE_SMOOTH ), null, null );
        }
        g2.dispose();

        this.bufferedImage = image;
    }

    public BufferedImage getImage()
    {
        if( bufferedImage == null )
            generateBufferedImage();

        return bufferedImage;
    }

    public Point getOffset()
    {
        return this.template.getOffset();
    }

    public Dimension getSize()
    {
        return this.template.getSize();
    }

    public void setOffset( Point offset )
    {
        //Do nothing - should be set by template
    }

    public void setSize( Dimension size )
    {
        //Do nothing - should be set by template
    }

    public void setID( String ID )
    {
        throw new UnsupportedOperationException( "Not supported." );
    }

    public String getID()
    {
        return this.template.getID();
    }

    public void setLoadedImage( LoadedImage img )
    {
        this.loadedImage = img;
        this.bufferedImage = null;
    }

    public LoadedImage getLoadedImage()
    {
        return this.loadedImage;
    }

    public void applyTransformation( AffineTransform transform )
    {
        if( this.transformationList == null )
            this.transformationList = new Vector<AffineTransform>();
        AffineTransform transformCopy = (AffineTransform) transform.clone();
        if( this.location == null )
            this.location = new Point( 0, 0 );
        
//        this.location.x = (int) transformCopy.getTranslateX();
//        this.location.y = (int) transformCopy.getTranslateY();
//        transformCopy.translate( -this.location.getX(), -this.location.getY() );
        this.transformationList.add( transformCopy );

        System.out.println( "ImageFrame translation: " + transform.getTranslateX() + ", " + transform.getTranslateY() );
        System.out.println( "ImageFrame scale: " + transform.getScaleX() + ", " + transform.getScaleY() );
        bufferedImage = null;
    }

    public AffineTransform getTransformation()
    {
        return generateTransform();
    }

    public void resetTransformations()
    {
        if( this.transformationList != null )
        {
            this.transformationList.clear();
            this.bufferedImage = null;
        }
    }

    public boolean hasTransformations()
    {
        boolean result = false;
        if( this.transformationList != null && !this.transformationList.isEmpty() )
        {
            result = true;
        }
        return result;
    }
}
